#include "Session.hpp"

Session::Session(tcp::socket socket)
    : control_socket_(std::move(socket)),
      input_buffer_(4096),
      data_socket_(control_socket_.get_executor())
{
    logger_ = spdlog::get("ftpserverlog");
    // 设置控制连接保持活跃
    boost::asio::socket_base::keep_alive option(true);
    control_socket_.set_option(option);
    command_handler_ = std::make_shared<CommandHandler>();

    // 设置当前工作目录为用户主目录
    try
    {
        current_dir_ = std::filesystem::current_path().string();
    }
    catch (const std::exception &e)
    {
        current_dir_ = ".";
        logger_->warn("Failed to get current directory: {}", e.what());
    }
}

void Session::Start()
{
    auto self = shared_from_this();
    // 设置CommandHandler中的Session引用
    command_handler_->SetSession(self);
    // 发送欢迎消息
    SendResponse(220, "Service ready for new user.");
    // 开始异步读取客户端命令
    ReadCommand();
}

void Session::SendResponse(int code, const std::string &msg)
{
    auto self(shared_from_this());
    std::string formatted = std::to_string(code) + " " + msg + "\r\n";

    boost::asio::async_write(
        control_socket_,
        boost::asio::buffer(formatted),
        [this, self, formatted](boost::system::error_code ec, std::size_t)
        {
            if (!IsSocketOpen())
            {
                logger_->warn("Socket closed during write operation");
                return;
            }
            if (!ec)
            {
                logger_->info("Send response successful: {}", formatted);
            }
            else
            {
                logger_->error("Send response failed: {}", ec.message());
                control_socket_.close();
            }
        });
}

void Session::ReadCommand()
{
    auto self(shared_from_this());
    if (!IsSocketOpen())
    {
        logger_->warn("Attempted to read from closed socket");
        return;
    }

    boost::asio::async_read_until(
        control_socket_,
        input_buffer_,
        '\n',
        [this, self](boost::system::error_code ec, std::size_t length)
        {
            if (!IsSocketOpen())
            {
                logger_->warn("Attempted to read from closed socket");
                return;
            }

            if (!ec)
            {
                std::string command;
                command.resize(length);
                input_buffer_.sgetn(&command[0], length);
                input_buffer_.consume(length);

                // 处理可能的\r\n结尾
                if (!command.empty() && command.back() == '\n')
                {
                    command.pop_back();
                    if (!command.empty() && command.back() == '\r')
                    {
                        command.pop_back();
                    }
                }

                logger_->info("Received from client: {}", command);
                HandleCommand(command);
                ReadCommand(); // 继续读取下一条命令
            }
            else
            {
                if (ec == boost::asio::error::eof)
                {
                    logger_->info("Client disconnected gracefully");
                }
                else
                {
                    logger_->error("Read error: {}", ec.message());
                }
                control_socket_.close();
            }
        });
}

void Session::HandleCommand(const std::string &command)
{
    if (!IsSocketOpen())
    {
        logger_->warn("Attempted to handle command on closed socket");
        return;
    }

    if (command.empty())
    {
        SendResponse(500, "Empty command");
        return;
    }

    try
    {
        command_handler_->Parse(command);
    }
    catch (const std::exception &e)
    {
        logger_->error("Command handling error: {}", e.what());
        SendResponse(500, "Internal server error");
    }
}

bool Session::IsSocketOpen() const
{
    return control_socket_.is_open() && !socket_closed_;
}

tcp::endpoint Session::GetRemoteEndpoint() const
{
    try
    {
        if (IsSocketOpen())
        {
            return control_socket_.remote_endpoint();
        }
        return tcp::endpoint();
    }
    catch (...)
    {
        return tcp::endpoint();
    }
}

Session::~Session()
{
    if (IsSocketOpen())
    {
        try
        {
            auto endpoint = GetRemoteEndpoint();
            logger_->info("Session destroyed for {}:{}",
                          endpoint.address().to_string(),
                          endpoint.port());
        }
        catch (const std::exception &e)
        {
            logger_->error("Error in session destructor: {}", e.what());
        }

        boost::system::error_code ec;
        control_socket_.close(ec);
        if (ec)
        {
            logger_->error("Error closing socket in destructor: {}", ec.message());
        }
    }

    // 关闭数据连接
    if (data_socket_.is_open())
    {
        boost::system::error_code ec;
        data_socket_.close(ec);
        if (ec)
        {
            logger_->error("Error closing data socket: {}", ec.message());
        }
    }
}
